#pragma once

/*************************	Header *****************************/

#include <armadillo>
#include <functional>

using arma::sp_cx_mat;
using arma::cx_vec;
using arma::vec;

/*********************** Declaration ***************************/

// The Lanczos Method Functor.
//
//	This function object is used to calculate the tri-diagonal
//	elements to level d using the Lanczos method. 
//	This functor include to date the calculation of the following:
//
//	-	The diagonal elements (alpha) and the off diagonal elements
//		(beta) of a tri-diagonalized version of a supplied sparse
//		matrix H with an inital state X
//
// Options:
//	The options are public variables (accessable from outside the
//	class) and are set to default value at class construction time.
//
// (size_t) N_states;			Default:	1000
//		An integer containing the numer of states (the dimension
//		or level d) to use in tri-diagonalization.
//		The N_states defaults to 1000.
//
// (func) updateProgress;	Default:	null
//		A function object containing an updating function to report
//		 the progress of calculations.
//		The updateProgress defaults to null i.e no function.
//
// Usage:
//	This function includes the following public operating functions.
//
//	(LanczosMethod &) operator()(sp_cx_mat H, cx_vec X)
//		This operator (use by simply appending () to a KPM type 
//		variable) calculates the elements of the tri-diagonalized 
//		matrix H_tilde. The operator returns the object it self for 
//		easy access to results.
//		The result is stored in the alpha and beta result variables. 
// 
// Example:
//	Set states and get tri-diagonalized elements:
//
//		LanczosMethod lm; // Generate a hamilton object
//
//		lm.N_states = current_states; // Set the current states
//
//		lm(H,X); // Calculate result.
//
//		alpha = lm.alpha; // Return result.
//		beta = lm.beta; // Return result.
class LanczosMethod
{
// Options:
public:
	// An integer containing the numer of states (the dimension
	// or level d) to use in tri-diagonalization.
	size_t N_states;
	// A function object containing an updating function to report
	// the progress of calculations.
	std::function< void (const double &)> updateProgress;

	
	// This operator (use by simply appending () to a KPM type 
	// variable) calculates the elements of the tri-diagonalized 
	// matrix H_tilde. The operator returns the object it self for 
	// easy access to results.
	// The result is stored in the alpha and beta result variables. 
	LanczosMethod & operator()(const sp_cx_mat &H,const  cx_vec &X);
	
// Results:
	// The diagonal of the resulting tri-diagonal matrix H_tilde.
	vec alpha;
	// The off-diagonal of the resulting tri-diagonal matrix H_tilde.
	vec beta;
	
// Constructor
	LanczosMethod();

protected:
	// This variable contains the update step
	double step;
	// This function attempts to update the progress.
	void try_updateProgress() const;
};

